package leetcode.Hot100;

import java.util.Arrays;
import java.util.LinkedList;

/**
 * @author Cheng Jun
 * Description:假设有打乱顺序的一群人站成一个队列，数组 people 表示队列中一些人的属性（不一定按顺序）。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ，前面 正好 有 ki 个身高大于或等于 hi 的人。
 * <p>
 * 请你重新构造并返回输入数组  people 所表示的队列。返回的队列应该格式化为数组 queue ，其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性（queue[0] 是排在队列前面的人）。
 * 输入：people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
 * 输出：[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
 * 解释：
 * 编号为 0 的人身高为 5 ，没有身高更高或者相同的人排在他前面。
 * 编号为 1 的人身高为 7 ，没有身高更高或者相同的人排在他前面。
 * 编号为 2 的人身高为 5 ，有 2 个身高更高或者相同的人排在他前面，即编号为 0 和 1 的人。
 * 编号为 3 的人身高为 6 ，有 1 个身高更高或者相同的人排在他前面，即编号为 1 的人。
 * 编号为 4 的人身高为 4 ，有 4 个身高更高或者相同的人排在他前面，即编号为 0、1、2、3 的人。
 * 编号为 5 的人身高为 7 ，有 1 个身高更高或者相同的人排在他前面，即编号为 1 的人。
 * 因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/queue-reconstruction-by-height
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @version 1.0
 * @date 2021/11/28 12:42
 * 一般这种数对，还涉及排序的，根据第一个元素正向排序，根据第二个元素反向排序，
 * 或者根据第一个元素反向排序，根据第二个元素正向排序，往往能够简化解题过程。
 * 二刷
 */
public class reconstructQueue {
    public static void main(String[] args) {
        reconstructQueue(new int[][]{new int[]{1, 1}, new int[]{2, 0}});
    }

    // 思路错误。。。先对身高进行正序排序，people[i][1] 的数字就是 该人所在的位置，如果该位置有人，就往后退一步，一直到没有人为止。
    static int[][] reconstructQueue(int[][] people) {
        int[][] resultQueue = new int[people.length][2];
        for (int[] item : resultQueue) {
            // 初始化身高为 -1，便于后面确认该位置是否有人
            item[0] = -1;
        }
        // 根据身高排序
        // Arrays.sort(people, (person1, person2) -> {
        //
        // });
        for (int i = 0; i < people.length; i++) {
            int index = people[i][1];
            while (true) {
                if (resultQueue[index][0] > -1) {
                    index++;
                } else {
                    resultQueue[index] = people[i];
                    break;
                }
            }
        }
        return resultQueue;
        // Arrays.sort(people, Comparator.comparingInt(item -> item[i]));
    }

    // 先按照高度进行排序，从大到小
    // 如果高度相同就按照k去排序，从小到大。
    // 后面只需要把排好序的people数组依次插入队列queue就行，插入的下标由k决定。
    // 因为后来插入队列的身高，都是比队列中的身高小，所以不会对队列中已存在的k产生影响。
    // 排序完的people： [[7,0], [7,1], [6,1], [5,0], [5,2]，[4,4]]
    // 插入的过程：
    //         ① 插入[7,0]：[[7,0]]
    //         ② 插入[7,1]：[[7,0],[7,1]]
    //         ③ 插入[6,1]：[[7,0],[6,1],[7,1]]
    //         ④ 插入[5,0]：[[5,0],[7,0],[6,1],[7,1]]
    //         ⑤ 插入[5,2]：[[5,0],[7,0],[5,2],[6,1],[7,1]]
    //         ⑥ 插入[4,4]：[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
    // 链接：https://leetcode-cn.com/problems/queue-reconstruction-by-height/solution/lin-tan-xin-by-linniu-zruv/
    static int[][] reconstructQueue1(int[][] people) {

        Arrays.sort(people, (p1, p2) -> {
            // 如果身高相等，就按照 k 从小到大排序
            if (p1[0] == p2[0]) return p1[1] - p2[1];
                // 身高不相等，按照 身高从大到小排序
            else return p2[0] - p1[0];
        });
        LinkedList<int[]> queue = new LinkedList<>();
        for (int[] array : people) {
            queue.add(array[1], array);
        }
        return queue.toArray(new int[people.length][]);
    }


}
